import { getToken } from './auth.js'
import config from '../config/index.js'

class WebSocketManager {
  constructor() {
    this.socketTask = null;
    this.isConnected = false;
    this.isReconnecting = false;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 500000;
    this.reconnectInterval = 3000; // 重连间隔时间（毫秒）
    this.listeners = new Map(); // 存储消息监听器
    this.messageQueue = []; // 存储待发送的消息队列

    // 心跳检测相关
    this.heartbeatInterval = null;
    this.heartbeatTimeout = null;
    this.pingTimeoutId = null;
    this.HEARTBEAT_INTERVAL = 30000; // 心跳间隔，30秒
    this.HEARTBEAT_TIMEOUT = 5000; // 心跳超时时间，5秒

    // 用户在线状态
    this.userInfo = {
      userId: null,
      userType: 'member' // 默认用户类型
    };
  }

  /**
   * 初始化WebSocket连接
   * @param {Object} options 连接选项
   */
  init(options = {}) {
    // 如果已经连接，则不再重复连接
    if (this.isConnected && this.socketTask) {
      console.log('WebSocket已连接，无需重新连接');
      return;
    }

    // 获取用户信息
    const token = getToken();
    if (!token) {
      console.warn('WebSocket连接失败: 未登录');
      return;
    }

    // 保存用户信息
    this.userInfo.userId = options.userId || uni.getStorageSync('userId');
    this.userInfo.userType = options.userType || 'member';

    try {
      // 构建WebSocket连接URL
      const baseURL = config.baseURL.replace(/^http/, 'ws');
      const wsUrl = `${baseURL}/infra/ws?token=${token}&userType=${this.userInfo.userType}`;

      console.log('正在连接WebSocket:', wsUrl);

      // 创建WebSocket连接
      this.socketTask = uni.connectSocket({
        url: wsUrl,
        success: () => {
          console.log('WebSocket连接创建成功');
        },
        fail: (error) => {
          console.error('WebSocket连接创建失败:', error);
          this.reconnect();
        }
      });

      // 监听WebSocket连接打开
      this.socketTask.onOpen(() => {
        console.log('WebSocket连接已打开');
        this.isConnected = true;
        this.reconnectAttempts = 0;

        // 发送队列中的消息
        this.flushMessageQueue();

        // 开始心跳检测
        this.startHeartbeat();

        // 发布用户上线状态
        console.log('===== 准备发送用户上线状态消息(im.user.online) =====');
        this.publishOnlineStatus(true);
        console.log('===== 已调用发送用户上线状态方法 =====');
      });

      // 监听WebSocket接收到服务器的消息
      this.socketTask.onMessage((res) => {
        this.handleMessage(res);
      });

      // 监听WebSocket关闭
      this.socketTask.onClose((res) => {
        console.log('WebSocket连接已关闭:', res);
        console.log('===== WebSocket连接关闭，无法发送用户离线状态 =====');
        this.isConnected = false;
        this.stopHeartbeat();

        // 如果不是主动关闭，则尝试重连
        if (!this.isReconnecting) {
          this.reconnect();
        }
      });

      // 监听WebSocket错误
      this.socketTask.onError((error) => {
        console.error('WebSocket连接错误:', error);
        console.log('===== WebSocket连接异常，无法发送用户离线状态 =====');
        this.isConnected = false;

        if (!this.isReconnecting) {
          this.reconnect();
        }
      });
    } catch (error) {
      console.error('WebSocket连接异常:', error);
      this.reconnect();
    }
  }

  /**
   * 处理接收到的WebSocket消息
   * @param {Object} res WebSocket消息对象
   */
  handleMessage(res) {
    console.log('收到WebSocket消息:', res.data);

    // 处理心跳响应
    if (res.data === 'pong') {
      clearTimeout(this.pingTimeoutId);
      return;
    }

    try {
      const message = JSON.parse(res.data);

      // 添加对消息类型的判断，确保能处理后端返回的JsonWebSocketMessage格式
      // 后端的JsonWebSocketMessage有type和content两个字段
      if (message && message.type) {
        // 特别记录在线状态相关的消息
        if (message.type === 'im.user.online') {
          console.log('===== 收到用户在线状态响应消息 =====', message);
          try {
            const content = typeof message.content === 'string' ?
              JSON.parse(message.content) : message.content;
            console.log(`===== 用户在线状态: ${content.isOnline ? '在线' : '离线'} =====`);
          } catch (e) {
            console.error('===== 解析用户在线状态消息内容失败 =====', e);
          }
        }

        // 处理视频通话相关消息
        this.handleVideoCallMessage(message);

        // 根据类型分发消息
        console.log(`收到类型为 ${message.type} 的消息`);

        // 向所有监听器分发消息
        this.notifyListeners(message);
      } else {
        console.log('消息格式不符合预期，可能不是JsonWebSocketMessage格式');
        // 仍然尝试分发消息，以防有监听器可以处理
        this.notifyListeners(message);
      }
    } catch (error) {
      console.error('解析WebSocket消息失败:', error);
    }
  }

  /**
   * 处理视频通话相关消息
   * @param {Object} message 消息对象
   */
  handleVideoCallMessage(message) {
    if (!message || !message.type) return;

    // 视频通话相关消息类型
    const videoCallTypes = [
      'video.call.invite',        // 通话邀请
      'video.call.accept',        // 接受通话
      'video.call.reject',        // 拒绝通话
      'video.call.cancel',        // 取消通话
      'video.call.hangup',        // 挂断通话
      'video.call.timeout',       // 通话超时
      'video.call.offer',             // WebRTC Offer
      'video.call.answer',            // WebRTC Answer
      'video.call.ice'     // ICE候选
    ];

    if (videoCallTypes.includes(message.type)) {
      console.log(`收到视频通话消息: ${message.type}`, message);

      try {
        // 解析消息内容
        const content = typeof message.content === 'string' ?
          JSON.parse(message.content) : message.content;

        // 触发视频通话事件
        this.triggerVideoCallEvent(message.type, content, message);
      } catch (error) {
        console.error('解析视频通话消息内容失败:', error);
      }
    }
  }

  /**
   * 触发视频通话事件
   * @param {String} eventType 事件类型
   * @param {Object} content 消息内容
   * @param {Object} originalMessage 原始消息
   */
  triggerVideoCallEvent(eventType, content, originalMessage) {
    // 向视频通话专用监听器分发消息
    this.listeners.forEach((callback, id) => {
      // 只向视频通话相关的监听器分发
      if (id.includes('video-call') || id.includes('webrtc')) {
        try {
          callback({
            type: eventType,
            content: content,
            originalMessage: originalMessage,
            timestamp: Date.now()
          });
        } catch (error) {
          console.error(`视频通话监听器(${id})处理消息失败:`, error);
        }
      }
    });

    // 同时向全局监听器分发（保持兼容性）
    this.notifyListeners(originalMessage);
  }

  /**
   * 向所有注册的监听器分发消息
   * @param {Object} message 消息对象
   */
  notifyListeners(message) {
    // 对所有监听器进行消息分发
    this.listeners.forEach((callback, id) => {
      try {
        callback(message);
      } catch (error) {
        console.error(`监听器(${id})处理消息失败:`, error);
      }
    });
  }

  /**
   * 添加消息监听器
   * @param {String} id 监听器ID
   * @param {Function} callback 回调函数
   */
  addListener(id, callback) {
    if (typeof callback !== 'function') {
      console.error('添加的监听器必须是一个函数');
      return false;
    }

    this.listeners.set(id, callback);
    console.log(`添加监听器: ${id}, 当前监听器数量: ${this.listeners.size}`);
    return true;
  }

  /**
   * 移除消息监听器
   * @param {String} id 监听器ID
   */
  removeListener(id) {
    const result = this.listeners.delete(id);
    console.log(`移除监听器: ${id}, 结果: ${result}, 当前监听器数量: ${this.listeners.size}`);
    return result;
  }

  /**
   * 开始心跳检测
   */
  startHeartbeat() {
    // 清除现有的心跳定时器
    this.stopHeartbeat();

    // 设置新的心跳定时器
    this.heartbeatInterval = setInterval(() => {
      if (this.isConnected) {
        // 发送心跳消息
        this.sendPing();

        // 设置心跳超时
        this.pingTimeoutId = setTimeout(() => {
          console.warn('心跳超时，断开连接并重新连接');
          this.close();
          this.reconnect();
        }, this.HEARTBEAT_TIMEOUT);
      }
    }, this.HEARTBEAT_INTERVAL);

    console.log('已启动WebSocket心跳检测');
  }

  /**
   * 停止心跳检测
   */
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }

    if (this.pingTimeoutId) {
      clearTimeout(this.pingTimeoutId);
      this.pingTimeoutId = null;
    }

    console.log('已停止WebSocket心跳检测');
  }

  /**
   * 发送心跳消息
   */
  sendPing() {
    this.send('ping');
  }

  /**
   * 发布用户在线状态
   * @param {Boolean} isOnline 是否在线
   */
  publishOnlineStatus(isOnline) {
    console.log(`===== 开始构建用户${isOnline ? '上线' : '离线'}状态消息 =====`);

    const messageContent = JSON.stringify({
      isOnline: isOnline
    });

    const message = {
      type: 'im.user.online',
      content: messageContent
    };

    console.log(`===== 即将发送用户${isOnline ? '上线' : '离线'}状态消息 =====`, message);
    this.send(message);
    console.log(`===== 用户${isOnline ? '上线' : '离线'}状态消息已发送 =====`);
  }

  /**
   * 发送视频通话消息
   * @param {String} type 消息类型
   * @param {Object} content 消息内容
   */
  sendVideoCallMessage(type, content) {
    const message = {
      type: type,
      content: JSON.stringify(content)
    };

    console.log(`发送视频通话消息: ${type}`, message);
    return this.send(message);
  }

  /**
   * 发送WebRTC信令消息
   * @param {Object} signalData 信令数据
   */
  sendWebRTCSignal(signalData) {
    return this.sendVideoCallMessage('im.webrtc.signaling', signalData);
  }

  /**
   * 发送消息
   * @param {Object|String} message 消息对象或字符串
   */
  send(message) {
    if (!this.isConnected || !this.socketTask) {
      console.warn('WebSocket未连接，消息将加入队列');
      if (typeof message === 'object' && message.type === 'im.user.online') {
        console.log('===== 用户在线状态消息因WebSocket未连接而加入队列 =====', message);
      }
      this.messageQueue.push(message);
      return false;
    }

    try {
      // 如果是字符串类型且不是心跳消息，将其转换为符合后端期望的JsonWebSocketMessage格式
      let data;
      let isOnlineStatusMessage = false;

      if (typeof message === 'string') {
        if (message === 'ping') {
          // 心跳消息保持原样
          data = message;
        } else {
          // 普通字符串消息，包装成JsonWebSocketMessage格式
          data = JSON.stringify({
            type: 'text.message',
            content: message
          });
        }
      } else if (typeof message === 'object') {
        // 记录是否为在线状态消息
        isOnlineStatusMessage = (message.type === 'im.user.online');

        // 确保对象消息有type和content字段
        if (!message.type) {
          console.warn('消息缺少type字段，添加默认type');
          message.type = 'default.message';
        }
        data = JSON.stringify(message);
      } else {
        console.error('不支持的消息类型');
        return false;
      }

      if (isOnlineStatusMessage) {
        console.log('===== 准备向服务器发送用户在线状态消息 =====', data);
      }

      this.socketTask.send({
        data,
        success: () => {
          if (isOnlineStatusMessage) {
            console.log('===== 用户在线状态消息发送成功 =====');
          } else {
            console.log('消息发送成功');
          }
        },
        fail: (error) => {
          if (isOnlineStatusMessage) {
            console.error('===== 用户在线状态消息发送失败 =====', error);
          } else {
            console.error('消息发送失败:', error);
          }
          // 如果发送失败，尝试重连
          if (error.errMsg.indexOf('断开') !== -1) {
            this.reconnect();
          }
        }
      });

      return true;
    } catch (error) {
      console.error('发送消息时发生错误:', error);
      if (typeof message === 'object' && message.type === 'im.user.online') {
        console.log('===== 用户在线状态消息发送过程中发生异常 =====');
      }
      return false;
    }
  }

  /**
   * 发送队列中的消息
   */
  flushMessageQueue() {
    if (this.messageQueue.length === 0) {
      return;
    }

    console.log(`发送队列中的${this.messageQueue.length}条消息`);

    // 复制并清空消息队列
    const messages = [...this.messageQueue];
    this.messageQueue = [];

    // 发送所有队列中的消息
    messages.forEach(message => {
      this.send(message);
    });
  }

  /**
   * 重新连接WebSocket
   */
  reconnect() {
    if (this.isReconnecting || this.reconnectAttempts >= this.maxReconnectAttempts) {
      if (this.reconnectAttempts >= this.maxReconnectAttempts) {
        console.warn(`WebSocket重连尝试次数已达上限(${this.maxReconnectAttempts}次)`);
      }
      return;
    }

    this.isReconnecting = true;
    this.reconnectAttempts++;

    console.log(`WebSocket正在尝试第${this.reconnectAttempts}次重连...`);

    // 关闭现有连接
    this.close(false);

    // 延迟一段时间后重新连接
    setTimeout(() => {
      this.init();
      this.isReconnecting = false;
    }, this.reconnectInterval);
  }

  /**
   * 关闭WebSocket连接
   * @param {Boolean} publishOffline 是否发布离线状态
   */
  close(publishOffline = true) {
    if (this.socketTask && this.isConnected) {
      // 发布用户离线状态
      if (publishOffline) {
        console.log('===== 主动关闭连接前，准备发送用户离线状态消息 =====');
        this.publishOnlineStatus(false);
        console.log('===== 用户离线状态消息发送方法已调用 =====');
      } else {
        console.log('===== 关闭连接但跳过发送用户离线状态消息 =====');
      }

      // 停止心跳检测
      this.stopHeartbeat();

      // 关闭WebSocket连接
      try {
        this.socketTask.close({
          success: () => {
            console.log('WebSocket连接已关闭');
          },
          fail: (error) => {
            console.error('关闭WebSocket连接失败:', error);
          },
          complete: () => {
            this.isConnected = false;
            this.socketTask = null;
          }
        });
      } catch (error) {
        console.error('关闭WebSocket连接时发生错误:', error);
        this.isConnected = false;
        this.socketTask = null;
      }
    } else {
      console.log('WebSocket已断开或未连接');
      this.isConnected = false;
      this.socketTask = null;
    }
  }

  /**
   * 获取连接状态
   */
  getStatus() {
    return {
      isConnected: this.isConnected,
      isReconnecting: this.isReconnecting,
      reconnectAttempts: this.reconnectAttempts,
      userInfo: this.userInfo,
      listenersCount: this.listeners.size,
      queuedMessages: this.messageQueue.length
    };
  }
}

// 创建单例
const webSocketManager = new WebSocketManager();

export default webSocketManager;
